It's not essential, but I'm asking out of curiosity. In Object type we can declare optional property by using ?: operator, but is there a similar shorthand when I want to declare the function return type?
type Type = string | number;
const foo = (): Type | undefined => {
...
return;
};
Just a heads up: ? (optional property) and | undefined are slightly different.
foo?: number means that the property foo may not exist at all on instances of the type. 'foo' in instance for example, will return false.
foo: number | undefined, however, requires that the foo is defined on the instance, even if its value is undefined.
There is no shorthand for this (that I know of or can find), but to avoid writing the union each time, and to improve the semantics, you can create a type to represent it. You can also make specific versions of this type, which can be useful, especially for nested generic types.
I have seen this pattern used in several real-world projects (VueUse, for example).
type Maybe<T> = T | undefined
type MaybeNumber = Maybe<number>
type MaybeArray<T> = Maybe<T[]>
type ArrayOfMaybe<T> = Maybe<T>[]
// Example use with variables:
let maybe: Maybe<string> = "Hello, world" // or `undefined`
let maybeNumber: MaybeNumber = 42 // or `undefined`
let maybeNumberArray: MaybeArray<number> = [1, 2, 3, 4] // or `undefined`
let arrayOfMaybeStrings: ArrayOfMaybe<string> = ["abc", undefined, "foo"]
It's generally simplest to just use the Maybe type directly.
The only cases where it's really beneficial to create a new type based on it is if it is widely used and/or more complex (e.g. unions and such).
Rambling and thoughts
The semantics of a shorthand like ?: would actually be nice for function return signatures, as you could semantically differentiate between "this function might return undefined as a value, and this is meaningful" (f(): T | undefined) and "this function might not return a meaningful value" (f()?: T). Of course, the fact that the function returned undefined instead of a value of type T must mean something, but the value undefined itself is not the point in that case, it is that no other value was returned.
No returning undefined is an option also. You can return the default value.
const foo = (): Type => {
let result: type = defaultValue;
...
return result || defaultValue;
};